﻿
namespace Behemoth.SharePoint.Branding {

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;

    using Behemoth.SharePoint.Logging;

    public class MasterPageTools : LoggingEventConsumerBase {

        #region Logging Code Pattern v2.0

        protected override string LOGGING_PRODUCT {
            get { return "Behemoth"; }
        }
        protected override string LOGGING_CATEGORY {
            get { return "Logging Example"; }
        }

        #endregion

        public bool DeleteMasterPageFiles(BrandingProperties brandProps) {
            Log("Invoking DeleteMasterPageFiles");

            string customizedMasterUrl = brandProps.CustomizedMasterUrl;
            SPWeb web = brandProps.RootWeb;
            string previewImageName = brandProps.MasterPagePreviewImageName;
            string subFolder1 = brandProps.MasterGallerySubFolder1;
            string subFolder2 = brandProps.MasterGallerySubFolder2;

            try {
                Log("Checking for existing file...");
                bool fileExists = FileTools.FileExists(web, customizedMasterUrl);
                if (fileExists) {
                    Log(string.Format("Found masterpage file '{0}' at root web {1}.", customizedMasterUrl, web.Url));
                    SPFile masterPage = web.GetFile(customizedMasterUrl);
                    SPFolder masterPageGallery = masterPage.ParentFolder;

                    // Workaround for SharePoint issue http://support.microsoft.com/kb/926812
                    // as solved by http://www.novolocus.com/2008/03/05/error-this-item-cannot-be-deleted-because-it-is-still-referenced-by-other-pages/
                    // http://www.katriendg.com/aboutdotnet/2007_1_cannot_delete_page_layout.aspx
                    FileTools.ForceFileDelete(web, customizedMasterUrl);

                    // also check for the preview image
                    SPFolder previewsFolder = masterPageGallery.SubFolders[subFolder1].SubFolders[subFolder2];
                    fileExists = previewsFolder.Exists; // dummy value designed to throw an error if the folder does not exist
                    Log(string.Format("PreviewFolder found at {0}. Deleting file {1}.", previewsFolder.Url, previewImageName));
                    if (previewsFolder.Files.Count == 1 && previewsFolder.Files[0].Name == previewImageName)
                    {
                        //previewsFolder.Delete();
                        // HACK deleting the folder doesn't seem like such a great idea
                        previewsFolder.Files[previewImageName].Delete();
                    } else if (previewsFolder.Files.Count > 1 && previewsFolder.Files[previewImageName].Exists) {
                        previewsFolder.Files[previewImageName].Delete();
                    }
                } else {
                    Log(string.Format("No masterpage file '{0}' found at root web '{1}'.", customizedMasterUrl, web.Url));
                }
            } catch (Exception ex) {
                Log(ex);
                return false;
            }
            Log("Completed DeleteMasterPageFiles");
            return true;
        }

        /// <summary>
        /// Turns on a master page.
        /// </summary>
        /// <param name="brandProps"></param>
        /// <param name="web"></param>
        public void ActivateMasterPage(BrandingProperties brandProps, SPWeb web) {
            string customizedMasterUrl = brandProps.CustomizedMasterUrl;
            bool customMasterFound = FileTools.FileExists(brandProps.RootWeb, customizedMasterUrl);
            if (!customMasterFound) {
                Log(string.Format("Custom master page {0} was not found. Exiting without action.", customizedMasterUrl));
                return;
            }
            web.AllowUnsafeUpdates = true;
            web.AllProperties["OldMasterUrl"] = web.MasterUrl;
            web.AllProperties["OldCustomMasterUrl"] = web.CustomMasterUrl;
            web.MasterUrl = customizedMasterUrl;
            web.CustomMasterUrl = customizedMasterUrl;

            // apply theme
            if (brandProps.ApplyThemeWithMasterPage) {
                string applyThemeName = brandProps.ThemeName;
                if (!string.IsNullOrEmpty(applyThemeName))
                    try {
                        web.ApplyTheme(applyThemeName);
                    } catch (Exception ex) {
                        Log(string.Format("Exception while applying theme name '{0}'.", brandProps.ThemeName), TraceSeverity.Unexpected);
                        Log(ex);
                    }
            }
        }

        /// <summary>
        /// Turns off the masterpage on a web.
        /// </summary>
        /// <param name="brandProps"></param>
        /// <param name="web"></param>
        public void DeactivateMasterPage(BrandingProperties brandProps, SPWeb web) {
            web.AllowUnsafeUpdates = true;
            string defaultMasterUrl = brandProps.DefaultMasterUrl;
            if (web.AllProperties.ContainsKey("OldMasterUrl")) {
                string oldMasterUrl = web.AllProperties["OldMasterUrl"].ToString();
                try {
                    // TODO this doesn't really work reliably, because the url doesn't really store a web relative address
                    // bool fileExists = web.GetFile( oldMasterUrl ).Exists;
                    web.MasterUrl = oldMasterUrl;
                } catch (Exception) {
                    web.MasterUrl = defaultMasterUrl;
                }
                web.AllProperties.Remove("OldMasterUrl");
            } else {
                // TODO check to see if the master for this web is actually the one we are dactivating
                web.MasterUrl = defaultMasterUrl;
            }

            if (web.AllProperties.ContainsKey("OldCustomMasterUrl")) {
                string oldCustomUrl = web.AllProperties["OldCustomMasterUrl"].ToString();
                try {
                    bool fileExists = web.GetFile(oldCustomUrl).Exists;
                    web.CustomMasterUrl = web.AllProperties["OldCustomMasterUrl"].ToString();
                } catch (ArgumentException) {
                    web.CustomMasterUrl = defaultMasterUrl;
                }
                web.AllProperties.Remove("OldCustomMasterUrl");
            } else {
                // TODO check to see if the master for this web is actually the one we are dactivating
                web.CustomMasterUrl = defaultMasterUrl;
            }

            // removed because it is handled by a different function
          /*
            if (brandProps.ApplyThemeWithMasterPage) {
                try {
                    web.ApplyTheme(ThemeTools.DEFAULT_THEME_NAME);
                } catch (Exception ex) {
                    Log(string.Format("Exception while applying theme name '{0}'.", ThemeTools.DEFAULT_THEME_NAME), TraceSeverity.Exception);
                    Log(ex);
                }
            }
           * */
        }

        /// <summary>
        /// Used to turn master pages on or off recursively.
        /// </summary>
        /// <param name="brandProps"></param>
        /// <param name="web"></param>
        /// <param name="isActivation"></param>
        /// <param name="recurseSubWebs"></param>
        /// <param name="WriteLog"></param>
        public void ProvisionMasterPages(BrandingProperties brandProps, SPWeb web, bool isActivation, bool recurseSubWebs) {
            Log(string.Format("Processing web {0}. isActivation={1} recurseSubWebs={2}", web.Url, isActivation, recurseSubWebs));
            if (isActivation) {
                ActivateMasterPage(brandProps, web);
            } else {
                DeactivateMasterPage(brandProps, web);
            }
            web.Update();
            if (!recurseSubWebs)
                return;
            foreach (SPWeb subWeb in web.Webs) {
                ProvisionMasterPages(brandProps, subWeb, isActivation, recurseSubWebs);
                subWeb.Dispose();
            }
        }

    } // class
} // namespace
